home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Utilities / Programming / EnterAct 3.5 / hAWK project / AWK Source / AWK_MAIN.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-08  |  21.6 KB  |  836 lines  |  [TEXT/TOPC]

  1. /* AWK_MAIN.C -- Expression tree constructors and main program for g/hawk. 
  2.  */
  3.  
  4. /* Copyright © 1986, 1988, 1989 1991 the Free Software Foundation, Inc.
  5.  *         This file is part of GAWK, the GNU implementation of the
  6.  * AWK Progamming Language, modified for the Macintosh (also called hAWK).
  7.  *         GAWK is free software; you can redistribute or modify
  8.  * it under the terms of the GNU General Public License as published by
  9.  * the Free Software Foundation; either version 1, or any later version.
  10.  *         GAWK is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13.  * GNU General Public License for more details.
  14.  *         You should have received a copy of the GNU General Public License
  15.  * along with GAWK; see the file "COPYING hAWK". If not, write to
  16.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  * Modified for THINK C 4 on the Macintosh by Ken Earle (Dynabyte) Aug 1991.
  18.  * Entirely revised to compile under CodeWarrior 6.1 sometime before Aug 95.
  19.  */
  20.  
  21. #include "AWK.H"
  22. #include "AppCodeComm.h"
  23. #include "PATCHLEV.H" /* just defines PATCHLEVEL == 10 */
  24. #include <signal.h>
  25.  
  26. extern short yyparse(void);
  27. extern void do_input(void);
  28. extern short close_io(void);
  29. extern void init_fields(void);
  30. extern short getopt(short argc, char **argv, char *opts);
  31. extern short re_set_syntax(short syntax);
  32. extern NODE *node(NODE *left, NODETYPE op, NODE *right);
  33.  
  34. short AWKmain(short argc, char **argv);
  35. static void usage(void);
  36. static void set_fs(char *str);
  37. static void init_vars(void);
  38. static void init_args(short argc0, short argc, char *argv0, char **argv);
  39. static void MakeOutAsInName(void);
  40. static NODE *spc_var(char *name, NODE *value);
  41. static void pre_assign(char *v);
  42. static void copyleft(void);
  43. SIGTYPE catchsig(int sig);
  44.  
  45. /* These nodes store all the special variables AWK uses */
  46. NODE *FS_node, *NF_node, *RS_node, *NR_node;
  47. NODE *FILENAME_node, *OFS_node, *ORS_node, *OFMT_node;
  48. NODE *FNR_node, *RLENGTH_node, *RSTART_node, *SUBSEP_node;
  49. NODE *ENVIRON_node, *IGNORECASE_node;
  50. NODE *ARGC_node, *ARGV_node; /* used primarily to hold the "leftover"
  51. file names to be used for input during program execution. See nextfile(). */
  52. NODE *RUNERR_node; /* Holds name of file to use for user error messages */
  53. NODE *STDPATH_node; /* Holds path to use as prefix for files to be written to
  54. same folder as stdout - typ looks like "Disk:folder1:...:folderN: */
  55. NODE /* *DAY_node, *DATE_node, */ *TIME_node; /* day, date, time (work in progress) */
  56. /*
  57.  * The parse tree and field nodes are stored here. Parse_end is a dummy
  58.  item used to free up unneeded fields without freeing the program being
  59.  run . NOTE can't find "Parse_end" anywhere. */
  60. short errcount = 0;    /* error counter, used by yyerror() */
  61.  
  62. /* The global null string */
  63. NODE *Nnull_string;
  64.  
  65. /* The name the program was invoked under, for error messages */
  66. char *myname;
  67.  
  68. /* A block of AWK code to be run before running the program */
  69. NODE *begin_block = 0;
  70.  
  71. /* A block of AWK code to be run after the last input file */
  72. NODE *end_block = 0;
  73.  
  74. NODE *expression_value; /* The block of AWK code that IS the program */
  75.  
  76. short exiting = 0;        /* Was an "exit" statement executed? */
  77. short exit_val = 0;        /* optional exit value */
  78.  
  79. #ifdef DEBUG
  80. /* non-zero means in debugging is enabled.  Probably not very useful */
  81. /* NOTE DEBUG is not yet supported in the Mac version. */
  82. short debugging = 0;
  83. extern short yydebug;
  84. #endif
  85.  
  86. short tempsource = 0;        /* source is in a temp file */
  87. char **sourcefile = NULL;    /* source file name(s) -see sourcefileNote */
  88. short numfiles = -1;        /* how many source files */
  89.  
  90. #define STRICT            /* keep it simple at first  */
  91. short strict = 0;            /* set to 1 below */
  92. /* NOTE ignoring the case while comparing strings and matching regular
  93. expressions is now allowed even if strict is nonzero, since it seems
  94. like a useful thing */
  95. short output_is_tty = 0;        /* control flushing of output */
  96.  
  97. char *stdOutAsInFileName = NULL; /* Holds stdout when used as input */
  98.  
  99. /*
  100.  * for strict to work, legal options must be first
  101.  *
  102.  * Unfortunately, -a and -e are orthogonal to -c.
  103.  */
  104. #define EXTENSIONS    8    /* where to clear */
  105. #ifdef DEBUG
  106. char awk_opts[14] /*= "F:f:v:caeCVdD"*/;
  107. /* colon means preceding option takes an argument */
  108. #else
  109. char awk_opts[12] /*= "F:f:v:caeCV"*/;
  110. #endif
  111.  
  112. /* Init functions, mainly since code resources are unhappy about
  113. initializing globals to an address. */
  114. void InitCommonsInAwkH(void); /* at bottom here */
  115. extern void InitAwkTabVars(void);
  116. extern void InitGetOpt(void);
  117. extern void InitEval(void);
  118. extern void InitField(void);
  119. extern void InitIO(void);
  120. extern void InitNode(void);
  121. extern void InitRegex(void);
  122. extern void InitRandom(void);
  123.  
  124. /* Revision: redirect stdout/err to text files, at end close them and
  125. free up all allocated memory. This function is largely unchanged for the
  126. Mac version, since hAWK_Interface.c creates a command line based on
  127. user mouse-waves. */
  128. short AWKmain(short argc, char **argv)
  129. {
  130. #ifdef DEBUG
  131.     /* Print out the parse tree.   For debugging */
  132.     register short dotree = 0;
  133. #endif
  134.     extern char *version_string; /* see VERSION.c */
  135.     FILE *fp, *textstdout, textstderr;
  136.     short c;
  137.     extern short opterr, optind;
  138.     extern char *optarg;
  139.      extern char *strrchr(); /* <string.h> */
  140.      extern char *tmpnam();    /* <stdio.h> */
  141.     short i;
  142.     short nostalgia;
  143. #ifdef somtime_in_the_future
  144.     short regex_mode = RE_SYNTAX_POSIX_EGREP;
  145. #else
  146.     short regex_mode = RE_SYNTAX_AWK;
  147. #endif
  148.     
  149.     extern Boolean gConcurrent;
  150.  
  151.     /* initialize variables */
  152.     InitCommonsInAwkH();
  153.     InitAwkTabVars();
  154.     InitGetOpt();
  155.     InitEval();
  156.     InitField();
  157.     InitIO();
  158.     InitNode();
  159.     InitRegex();
  160.     if (!hAWKstackDepth)
  161.         InitRandom();
  162.     
  163.     if (!hAWKstackDepth)
  164.         {
  165.         if (strncmp(version_string, "@(#)", 4) == 0)
  166.             version_string += 4;
  167.  
  168.         (void) signal(SIGFPE, catchsig); /* <signal.h> div by zero etc */
  169.  
  170.         /* redirect stderr to text file. stdout is reopened in
  171.         init_args - postponed because reopening it now would
  172.         zero it out, and user may want to take input from
  173.         stdout (ie the results of the last Drag_on Module run. */
  174.         if (!freopen(gacc.stdErrFileName, "w", stderr))
  175.             /* fatal error */
  176.             exit(1);
  177.         }
  178.     
  179.     /* Pick out "AWK" or somesuch from first argument */
  180.     myname = strrchr(argv[0], '/');
  181.     if (myname == NULL)
  182.         myname = argv[0]; /* typical case, since not using '/' */
  183.     else
  184.         myname++;
  185.     if (argc < 2)
  186.         usage();
  187.  
  188.     /* initialize the null string */
  189.     Nnull_string = make_string("", 0);
  190.     Nnull_string->numbr = 0.0;
  191.     Nnull_string->type = Node_val;
  192.     Nnull_string->flags = (PERM|STR|NUM|NUMERIC);
  193.  
  194.     /* Set up the special variables */
  195.  
  196.     /*
  197.      * Note that this must be done BEFORE arg parsing else -F
  198.      * breaks horribly 
  199.      */
  200.     init_vars();
  201.     
  202.     
  203.  
  204.     /* worst case */
  205.     emalloc(sourcefile, char **, argc * sizeof(char *), "main");
  206.     
  207. #ifdef STRICT    /* strict new awk compatibility */
  208.     strict = 1;
  209.     awk_opts[EXTENSIONS] = '\0';
  210. #endif
  211.  
  212. #ifndef STRICT
  213.     /* undocumented feature, inspired by nostalgia, and a T-shirt */
  214.     nostalgia = 0;
  215.     for (i = 1; i < argc && argv[i][0] == '-'; i++) {
  216.         if (argv[i][1] == '-')        /* -- */
  217.             break;
  218.         else if (argv[i][1] == 'c') {    /* compatibility mode */
  219.             nostalgia = 0;
  220.             break;
  221.         } else if (STREQ(&argv[i][1], "nostalgia"))
  222.             nostalgia = 1;
  223.             /* keep looping, in case -c after -nostalgia */
  224.     }
  225.     if (nostalgia) {
  226.         fprintf (stderr, "awk: bailing out near line 1\n");
  227.         abort();
  228.     }
  229. #endif
  230.     
  231.     /* AWK options: see AWKOptionsNote */
  232.     while ((c = getopt (argc, argv, awk_opts)) != EOF) {
  233.         switch (c) {
  234.         /* Note '--' is detected by getopt() */
  235. #ifdef DEBUG
  236.         case 'd':
  237.             debugging++;
  238.             dotree++;
  239.             break;
  240.  
  241.         case 'D':
  242.             debugging++;
  243.             yydebug = 2;
  244.             break;
  245. #endif
  246.  
  247. #ifndef STRICT
  248.         case 'c':
  249.             strict = 1;
  250.             break;
  251. #endif
  252.  
  253.         case 'F':
  254.             set_fs(optarg);
  255.             break;
  256.  
  257.         case 'f':
  258.             /*
  259.              * a la MKS awk, allow multiple -f options.
  260.              * this makes function libraries real easy.
  261.              * most of the magic is in the scanner.
  262.              NOTE each source file to be preceded by '-f' */
  263.              
  264.              /* REVISION RecordSourceFile() */
  265.             sourcefile[++numfiles] = optarg;
  266.             break;
  267.  
  268.         case 'v':
  269.             pre_assign(optarg);
  270.             break;
  271.  
  272.         case 'V':
  273.             fprintf(stderr, "%s, patchlevel %d\n",
  274.                     version_string, PATCHLEVEL);
  275.             break;
  276.  
  277.         case 'C':
  278.             copyleft();
  279.             break;
  280.  
  281.         case 'a':    /* use old fashioned awk regexps */
  282.             regex_mode = RE_SYNTAX_AWK;
  283.             break;
  284.  
  285.         case 'e':    /* use egrep style regexps, per Posix */
  286.             regex_mode = RE_SYNTAX_POSIX_EGREP;
  287.             break;
  288.  
  289.         case '?':
  290.         default:
  291.             /* getopt will print a message for us */
  292.             /* S5R4 awk ignores bad options and keeps going */
  293.             break;
  294.         }
  295.     }
  296.  
  297.     /* Tell the regex routines how they should work. . . */
  298.     (void) re_set_syntax(regex_mode);
  299.  
  300. #ifdef DEBUG
  301.     setbuf(stdout, (char *) NULL);    /* make debugging easier */
  302. #endif
  303. //    if (isatty(fileno(stdout)))
  304. //        output_is_tty = 1;
  305.     /* No -f option, use next arg */
  306.     /* write to temp file and save sourcefile name */
  307.     if (numfiles == -1) {
  308.         short i;
  309.  
  310.         if (optind > argc - 1)    /* no args left */
  311.             usage();
  312.         numfiles++;
  313.         i = strlen (argv[optind]);
  314.         if (i == 0) {    /* sanity check */
  315.             fprintf(stderr, "%s: empty program text\n", myname);
  316.             usage();
  317.             /* NOTREACHED */
  318.         }
  319.         sourcefile[0] = tmpnam((char *) NULL);
  320.         if ((fp = fopen (sourcefile[0], "w")) == NULL)
  321.             fatal("could not save source prog in temp file (%s)",
  322.             strerror(errno));
  323.         if (fwrite (argv[optind], 1, i, fp) == 0)
  324.             fatal(
  325.             "could not write source program to temp file (%s)",
  326.             strerror(errno));
  327.         if (argv[optind][i-1] != '\n')
  328.             putc ('\n', fp);
  329.         (void) fclose (fp);
  330.         tempsource++;
  331.         optind++;
  332.     }
  333.     /* This builds list of input files to ARGVnode */
  334.     init_args(optind, argc, myname, argv);
  335.     
  336.     errcount = 0;
  337.     if (!gConcurrent)
  338.         CheckForInterrupt();
  339.     
  340.     /* Read in the program */
  341.     if (yyparse() || errcount)
  342.         exit(1);
  343.     if (!gConcurrent)
  344.         CheckForInterrupt();
  345. #ifdef DEBUG
  346.     if (dotree)
  347.         print_parse_tree(expression_value);
  348. #endif
  349.     /* Set up the field variables */
  350.     init_fields();
  351.     
  352.     if (begin_block)
  353.         (void) interpret(begin_block);
  354.     if (gConcurrent)
  355.         {
  356.         if (CheckInWithCallingApp())  /* CodeResource_Helper.c */
  357.             JumpOnHAWKError(999);
  358.         }
  359.     else
  360.         CheckForInterrupt();
  361.     if (!exiting && (expression_value || end_block))
  362.         do_input();
  363.     if (!gConcurrent)
  364.         CheckForInterrupt();
  365.     if (end_block)
  366.         (void) interpret(end_block);
  367.     if (close_io() != 0 && exit_val == 0)
  368.         exit_val = 1;
  369.  
  370.     /* REACHED */
  371.     return exit_val;
  372. }
  373.  
  374. static void
  375. usage()
  376. {
  377.     char *opt1 = " -f progfile [--]";
  378.     char *opt2 = " [--] 'program'";
  379. #ifdef STRICT
  380.     char *regops = " [-ae] [-F fs] [-v var=val]";
  381. #else
  382.     char *regops = " [-aecCV] [-F fs] [-v var=val]";
  383. #endif
  384.  
  385.     fprintf(stderr, "usage: %s%s%s file ...\n       %s%s%s file ...\n",
  386.         myname, regops, opt1, myname, regops, opt2);
  387.     exit(11);
  388. }
  389.  
  390. /* Generate compiled regular expressions */
  391. struct re_pattern_buffer *
  392. make_regexp(NODE *s, short ignorecase)
  393. {
  394.     struct re_pattern_buffer *rp;
  395.     char *err;
  396.  
  397.     emalloc(rp, struct re_pattern_buffer *, sizeof(*rp), "make_regexp");
  398.     memset((char *) rp, 0, sizeof(*rp));
  399.     emalloc(rp->buffer, char *, 16, "make_regexp");
  400.     rp->allocated = 16;
  401.     emalloc(rp->fastmap, char *, 256, "make_regexp");
  402.  
  403.     if (/*! strict && */ ignorecase)
  404.         rp->translate = casetable;
  405.     else
  406.         rp->translate = NULL;
  407.     if ((err = re_compile_pattern(s->stptr, s->stlen, rp)) != NULL)
  408.         fatal("%s: /%s/", err, s->stptr);
  409.     free_temp(s);
  410.     return rp;
  411. }
  412.  
  413. struct re_pattern_buffer *
  414. mk_re_parse(char *s, short ignorecase)
  415. {
  416.     char *src;
  417.     register char *dest;
  418.     register short c;
  419.     short in_brack = 0;
  420.  
  421.     for (dest = src = s; *src != '\0';) {
  422.         if (*src == '\\') {
  423.             c = *++src;
  424.             switch (c) {
  425.             case '/':
  426.             case 'a':
  427.             /*case 'b':*/
  428.             case 'f':
  429.             case 'n':
  430.             case 'r':
  431.             case 't':
  432.             case 'v':
  433.             case 'x':
  434.             case '0':
  435.                 c = parse_escape(&src);
  436.                 if (c < 0)
  437.                     cant_happen();
  438.                 *dest++ = (char)c;
  439.                 break;
  440.             case '1':
  441.             case '2':
  442.             case '3':
  443.             case '4':
  444.             case '5':
  445.             case '6':
  446.             case '7':
  447.                 if (*(src+1) >= '0' && *(src+1) <= '7')
  448.                     {
  449.                     c = parse_escape(&src);
  450.                     if (c < 0)
  451.                         cant_happen();
  452.                     *dest++ = (char)c;
  453.                     }
  454.                 else
  455.                     {
  456.                     *dest++ = '\\';
  457.                     *dest++ = (char)c;
  458.                     src++;
  459.                     }
  460.                 break;
  461.             default:
  462.                 *dest++ = '\\';
  463.                 *dest++ = (char)c;
  464.                 src++;
  465.                 break;
  466.             }
  467.         } else if (*src == '/' && ! in_brack)
  468.             break;
  469.         else {
  470.             if (*src == '[')
  471.                 in_brack = 1;
  472.             else if (*src == ']')
  473.                 in_brack = 0;
  474.  
  475.             *dest++ = *src++;
  476.         }
  477.     }
  478.     return make_regexp(tmp_string(s, (short)(dest-s)), ignorecase);
  479. }
  480.  
  481. /* This replaced by "About" button in main dialog. */
  482. static void
  483. copyleft ()
  484. {
  485.     extern char *version_string;
  486.     char *cp;
  487.     static char blurb[] =
  488. "Copyright (C) 1989, Free Software Foundation.\n\
  489. GNU Awk comes with ABSOLUTELY NO WARRANTY.  This is free software, and\n\
  490. you are welcome to distribute it under the terms of the GNU General\n\
  491. Public License, which covers both the warranty information and the\n\
  492. terms for redistribution.\n\n\
  493. You should have received a copy of the GNU General Public License along\n\
  494. with this program; if not, write to the Free Software Foundation, Inc.,\n\
  495. 675 Mass Ave, Cambridge, MA 02139, USA.\n";
  496.  
  497.     fprintf (stderr, "%s, patchlevel %d\n", version_string, PATCHLEVEL);
  498.     fputs(blurb, stderr);
  499.     fflush(stderr);
  500. }
  501.  
  502. static void
  503. set_fs(char *str)
  504. {
  505.     register NODE **tmp;
  506.  
  507.     tmp = get_lhs(FS_node, 0);
  508.     /*
  509.      * Only if in full compatibility mode check for the stupid special
  510.      * case so -F\t works as documented in awk even though the shell
  511.      * hands us -Ft.  Bleah!
  512.      */
  513.     if (strict && str[0] == 't' && str[1] == '\0')
  514.         str[0] = '\t';
  515.     *tmp = make_string(str, 1);
  516.     do_deref();
  517. }
  518.  
  519. static void
  520. init_args(short argc0, short argc, char *argv0, char **argv)
  521.     {
  522.     short i, j;
  523.     NODE **aptr;
  524.     Boolean    stdOutReset = FALSE;
  525.  
  526.     ARGV_node = spc_var("ARGV", Nnull_string);
  527.     aptr = assoc_lookup(ARGV_node, tmp_number(0.0));
  528.     *aptr = make_string(argv0, strlen(argv0));
  529.     for (i = argc0, j = 1; i < argc; i++)
  530.         {
  531.         /* Allow stdout from last run to be used as input for this
  532.         run; since stdout is overwritten, first save its contents under
  533.         a new name. This quietly changes the name of stdout stored in
  534.         ARGV[] which would throw off redirection, but normally one does
  535.         not both take input from stdout and redirect output to one of the
  536.         input files. */
  537.         if (!strcmp(argv[i], gacc.stdOutFileName))
  538.             {
  539.             if (stdOutAsInFileName == NULL)
  540.                 MakeOutAsInName();
  541.             fclose(stdout);/* ignore error if not open */
  542.             remove(stdOutAsInFileName); /* ignore error if doesn't exist */
  543.             rename(gacc.stdOutFileName, stdOutAsInFileName);/* fails if stdout not there... */
  544.             stdOutReset = TRUE;
  545.             aptr = assoc_lookup(ARGV_node, tmp_number((AWKNUM) j));
  546.             *aptr = make_string(stdOutAsInFileName, strlen(stdOutAsInFileName));
  547.             }
  548.         else
  549.             {
  550.             aptr = assoc_lookup(ARGV_node, tmp_number((AWKNUM) j));
  551.             *aptr = make_string(argv[i], strlen(argv[i]));
  552.             }
  553.         j++;
  554.         }
  555.     ARGC_node = spc_var("ARGC", make_number((AWKNUM) j));
  556.     
  557.     /* stdout is finally safe to (re)open */
  558.     if (!hAWKstackDepth || stdOutReset)
  559.         {
  560.         if (!freopen(gacc.stdOutFileName, "w", stdout))
  561.             /* fatal error */
  562.             exit(1);
  563.         }
  564.     }
  565.  
  566. /* Set global stdOutAsInFileName to temp file name to use for
  567. stdout file which will be used for current input. 
  568. Typ stdOutAsInFileName = "Disk:...:THINK C folder:$tempOutAsInput" */
  569. static void MakeOutAsInName()
  570.     {
  571.     char     *var;
  572.     short     i;
  573.     
  574.     var = gacc.stdOutFileName;
  575.     i = strlen(gacc.stdOutFileName);
  576.     while (*(var + i - 1) != ':' && i > 0)
  577.         --i;
  578.     /* note the trailing colon is kept */
  579.     emalloc(stdOutAsInFileName, char *, i+16, "init_args");
  580.     BlockMove(gacc.stdOutFileName, stdOutAsInFileName, i);
  581.     BlockMove("$tempOutAsInput", stdOutAsInFileName+i, 16);
  582.     }
  583.  
  584. /*
  585.  * Set all the special variables to their initial values.
  586.  ENVIRION not done for the Mac version.
  587.  */
  588. static void
  589. init_vars()
  590. {
  591. #ifndef MACVERSION
  592.     extern char **environ;
  593. #endif
  594.     char         *var, *val, temp[3];
  595.     NODE         **aptr;
  596.     time_t        now;
  597.     struct tm    *date;
  598.     char        s[50];
  599.     short         i;
  600.  
  601.     FS_node = spc_var("FS", make_string(" ", 1));
  602.     NF_node = spc_var("NF", make_number(-1.0));
  603.     RS_node = spc_var("RS", make_string("\n", 1));
  604.     NR_node = spc_var("NR", make_number(0.0));
  605.     FNR_node = spc_var("FNR", make_number(0.0));
  606.     FILENAME_node = spc_var("FILENAME", make_string("-", 1));
  607.     OFS_node = spc_var("OFS", make_string(" ", 1));
  608.     ORS_node = spc_var("ORS", make_string("\n", 1));
  609.     OFMT_node = spc_var("OFMT", make_string("%.6g", 4));
  610.     RLENGTH_node = spc_var("RLENGTH", make_number(0.0));
  611.     RSTART_node = spc_var("RSTART", make_number(0.0));
  612.     SUBSEP_node = spc_var("SUBSEP", make_string("\034", 1));
  613.     IGNORECASE_node = spc_var("IGNORECASE", make_number(0.0));
  614.  
  615.     ENVIRON_node = spc_var("ENVIRON", Nnull_string);
  616. #ifdef MACVERSION
  617.     /* the stdErrFileName is $tempStdErr, whereas the RUNERR file name is
  618.     $tempRunErr. */
  619.     var = gacc.stdErrFileName;
  620.     i = strlen(gacc.stdErrFileName);
  621.     if (i >= 6)
  622.         {
  623.         temp[0] = var[i-6];
  624.         var[i-6] = 'R';
  625.         temp[1] = var[i-5];
  626.         var[i-5] = 'u';
  627.         temp[2] = var[i-4];
  628.         var[i-4] = 'n';
  629.         RUNERR_node = spc_var("RUNERR", make_string(gacc.stdErrFileName, i));
  630.         var[i-6] = temp[0];
  631.         var[i-5] = temp[1];
  632.         var[i-4] = temp[2];
  633.         }
  634.     /* STDPATH holds path name to be used as prefix for any file that is to be 
  635.     written to the same folder as stdout. */
  636.     while (*(var + i - 1) != ':' && i > 0)
  637.         --i;
  638.     /* note the trailing colon is kept */
  639.     STDPATH_node = spc_var("STDPATH", make_string(gacc.stdErrFileName, i));
  640.     
  641.     /* Date/time */
  642.     now = time(NULL);
  643.     date = localtime(&now);
  644.     i = strftime(s,50, "%A, %B %d, %Y %I:%M %p", date);
  645.     TIME_node = spc_var("TIME", make_string(s, i));
  646.     /* work in progress ****************
  647.     i = strftime(s,50, "%A", date);
  648.     DAY_node = spc_var("DAY", make_string(s, i));
  649.     i = strftime(s,50, "%B %d, %Y", date);
  650.     DATE_node = spc_var("DATE", make_string(s, i));
  651.     i = strftime(s,50, "%I:%M:%S %p", date);
  652.     TIME_node = spc_var("TIME", make_string(s, i));
  653.     *********/
  654.     
  655.     return;
  656.     
  657. #else
  658.     for (i = 0; environ[i]; i++) {
  659.         static char nullstr[] = "";
  660.  
  661.         var = environ[i];
  662.         val = strchr(var, '=');
  663.         if (val)
  664.             *val++ = '\0';
  665.         else
  666.             val = nullstr;
  667.         aptr = assoc_lookup(ENVIRON_node, tmp_string(var, strlen (var)));
  668.         *aptr = make_string(val, strlen (val));
  669.  
  670.         /* restore '=' so that system() gets a valid environment */
  671.         if (val != nullstr)
  672.             *--val = '=';
  673.     }
  674. #endif
  675. }
  676.  
  677. /* Create a special variable */
  678. static NODE *
  679. spc_var(char *name, NODE *value)
  680. {
  681.     register NODE *r;
  682.  
  683.     if ((r = lookup(variables, name)) == NULL)
  684.         r = install(variables, name, node(value, Node_var, (NODE *) NULL));
  685.     return r;
  686. }
  687.  
  688. static void
  689. pre_assign(char *v)
  690. {
  691.     char *cp;
  692.  
  693.     cp = strchr(v, '=');
  694.     if (cp != NULL) {
  695.         *cp++ = '\0';
  696.         variable(v)->var_value = make_string(cp, strlen(cp));
  697.     } else {
  698.         fprintf (stderr,
  699.             "%s: '%s' argument to -v not in 'var=value' form\n",
  700.                 myname, v);
  701.         usage();
  702.     }
  703. }
  704.  
  705.  
  706. SIGTYPE catchsig(int sig)
  707. {
  708. extern void msg(char *va_alist, ...);
  709.  
  710.     if (sig == SIGFPE) {
  711.         fatal("floating point exception");
  712.     } else if (sig == SIGSEGV) {
  713.         msg("fatal error: segmentation fault");
  714.         /* fatal won't abort() if not compiled for debugging */
  715.         abort();
  716.     } else
  717.         cant_happen();
  718.     /* NOTREACHED */
  719. }
  720.  
  721. void InitCommonsInAwkH()
  722.     {
  723.     extern char *version_string; /* see VERSION.c */
  724.     version_string = "@(#)Gnu Awk (gawk) 2.11.1";
  725.     
  726.     if (!hAWKstackDepth)
  727.         {
  728. #ifdef DEBUG
  729.     strcpy(awk_opts, "F:f:v:caeCVdD");
  730. /* colon means preceding option takes an argument */
  731. #else
  732.     strcpy(awk_opts, "F:f:v:caeCV");
  733. #endif
  734.         }
  735.     exiting = 0;        /* Was an "exit" statement executed? */
  736.     exit_val = 0;        /* optional exit value */
  737.     tempsource = 0;        /* source is in a temp file */
  738.     sourcefile = NULL;    /* source file name(s) -see sourcefileNote */
  739.     numfiles = -1;        /* how many source files */
  740.     output_is_tty = 0;        /* control flushing of output */
  741.     /* gawk builtin variables */
  742.     FS_node = NF_node = RS_node = NR_node = NULL;
  743.     FILENAME_node = OFS_node = ORS_node = OFMT_node = NULL;
  744.     FNR_node = RLENGTH_node = RSTART_node = SUBSEP_node = NULL;
  745.     IGNORECASE_node = NULL;
  746.     
  747.     stack_ptr = NULL;
  748.     Nnull_string = NULL;
  749.     deref = NULL;
  750.     fields_arr = NULL;
  751.     sourceline = 0;
  752.     source = NULL;
  753.     expression_value = NULL;
  754.     _t = NULL;    /* used as temporary in tree_eval */
  755.     myname = NULL;
  756.     node0_valid = 1;
  757.     }
  758.  
  759. void SaveCommonsInAwkH(void);
  760. void RestoreCommonsInAwkH(void);
  761. void SaveCommonsInAwkH()
  762.     {
  763.     hs->exiting = exiting;
  764.     hs->exit_val = exit_val;
  765.     hs->tempsource = tempsource;
  766.     hs->sourcefile = sourcefile;
  767.     hs->numfiles = numfiles;
  768.     hs->output_is_tty = output_is_tty;
  769.     hs->FS_node = FS_node;
  770.     hs->NF_node = NF_node;
  771.     hs->RS_node = RS_node;
  772.     hs->NR_node = NR_node;
  773.     hs->FILENAME_node = FILENAME_node;
  774.     hs->OFS_node = OFS_node;
  775.     hs->ORS_node = ORS_node;
  776.     hs->OFMT_node = OFMT_node;
  777.     hs->FNR_node = FNR_node;
  778.     hs->RLENGTH_node = RLENGTH_node;
  779.     hs->RSTART_node = RSTART_node;
  780.     hs->SUBSEP_node = SUBSEP_node;
  781.     hs->IGNORECASE_node = IGNORECASE_node;
  782.     hs->ARGC_node = ARGC_node;
  783.     hs->ARGV_node = ARGV_node;
  784.     hs->RUNERR_node = RUNERR_node;
  785.     hs->STDPATH_node = STDPATH_node;
  786.     hs->TIME_node = TIME_node;
  787.     hs->stack_ptr = stack_ptr;
  788.     hs->deref = deref;
  789.     hs->fields_arr = fields_arr;
  790.     hs->sourceline = sourceline;
  791.     hs->source = source;
  792.     hs->expression_value = expression_value;
  793.     hs->_t = _t;
  794.     hs->myname = myname;
  795.     hs->node0_valid = node0_valid;
  796.     
  797.     }
  798.  
  799. void RestoreCommonsInAwkH()
  800.     {
  801.     exiting = hs->exiting;
  802.     exit_val = hs->exit_val;
  803.     tempsource = hs->tempsource;
  804.     sourcefile = hs->sourcefile;
  805.     numfiles = hs->numfiles;
  806.     output_is_tty = hs->output_is_tty;
  807.     FS_node = hs->FS_node;
  808.     NF_node = hs->NF_node;
  809.     RS_node = hs->RS_node;
  810.     NR_node = hs->NR_node;
  811.     FILENAME_node = hs->FILENAME_node;
  812.     OFS_node = hs->OFS_node;
  813.     ORS_node = hs->ORS_node;
  814.     OFMT_node = hs->OFMT_node;
  815.     FNR_node = hs->FNR_node;
  816.     RLENGTH_node = hs->RLENGTH_node;
  817.     RSTART_node = hs->RSTART_node;
  818.     SUBSEP_node = hs->SUBSEP_node;
  819.     IGNORECASE_node = hs->IGNORECASE_node;
  820.     ARGC_node = hs->ARGC_node;
  821.     ARGV_node = hs->ARGV_node;
  822.     RUNERR_node = hs->RUNERR_node;
  823.     STDPATH_node = hs->STDPATH_node;
  824.     TIME_node = hs->TIME_node;
  825.     stack_ptr = hs->stack_ptr;
  826.     deref = hs->deref;
  827.     fields_arr = hs->fields_arr;
  828.     sourceline = hs->sourceline;
  829.     source = hs->source;
  830.     expression_value = hs->expression_value;
  831.     _t = hs->_t;
  832.     myname = hs->myname;
  833.     node0_valid = hs->node0_valid;
  834.     
  835.     }
  836.